﻿using Microsoft.VisualStudio.Modeling.Design;
using System.ComponentModel;
using Microsoft.VisualStudio.Modeling;
using System;
using System.Collections.Generic;

namespace Dslfactory.wcfLanguage
{
 #region Type descriptor for DataContract
 /// <summary>
	/// Factory class for DataMemberTypeDescriptors.
	/// </summary>
	internal class DataContractDescriptionProvider : ElementTypeDescriptionProvider
	{
		/// <summary>
		/// Called by the System.ComponentModel framework when it requires a type descriptor instance.
		/// </summary>
		protected override ElementTypeDescriptor CreateTypeDescriptor(ICustomTypeDescriptor parent, ModelElement element)
		{
			return new DataContractTypeDescriptor(parent, element);
		}
	}
	
	/// <summary>
	/// Custom type descriptor class for DataMember elements.
	/// </summary>
	public partial class DataContractTypeDescriptor : ElementTypeDescriptor
	{
		/// <summary>
		/// Creates a new DataMemberTypeDescriptor.
		/// </summary>
  public DataContractTypeDescriptor(ICustomTypeDescriptor parent, ModelElement selectedElement) : base(parent, selectedElement) { }
	
		/// <summary>
		/// Returns a collection of property descriptors an instance of DataMember.
		/// </summary>
		public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
		{
			PropertyDescriptorCollection propertyDescriptors = base.GetProperties(attributes);
   List<ElementPropertyDescriptor> toRemove = new List<ElementPropertyDescriptor>();

			// Remove the properties that should not be shown when the class is not a DataContract
   DataContract source = this.ModelElement as DataContract;
   if ((source != null) && (!source.IsDataContract))
    foreach (ElementPropertyDescriptor propertyDescriptor in propertyDescriptors)
     if ((propertyDescriptor.DomainPropertyInfo.Id == DataContract.DataContractNameDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == DataContract.DataContractNamespaceDomainPropertyId)
        )
      toRemove.Add(propertyDescriptor);

   foreach (PropertyDescriptor propertyDescriptor in toRemove)
    propertyDescriptors.Remove(propertyDescriptor);
				
			return propertyDescriptors;
		}
 }
 #endregion

 #region Type descriptor for DataMember
 /// <summary>
 /// Factory class for DataMemberTypeDescriptors.
 /// </summary>
 internal class DataMemberDescriptionProvider : ElementTypeDescriptionProvider
 {
  /// <summary>
  /// Called by the System.ComponentModel framework when it requires a type descriptor instance.
  /// </summary>
  protected override ElementTypeDescriptor CreateTypeDescriptor(ICustomTypeDescriptor parent, ModelElement element)
  {
   return new DataMemberTypeDescriptor(parent, element);
  }
 }

 /// <summary>
 /// Custom type descriptor class for DataMember elements.
 /// </summary>
 public partial class DataMemberTypeDescriptor : ElementTypeDescriptor
 {
  /// <summary>
  /// Creates a new DataMemberTypeDescriptor.
  /// </summary>
  public DataMemberTypeDescriptor(ICustomTypeDescriptor parent, ModelElement selectedElement) : base(parent, selectedElement) { }

  /// <summary>
  /// Returns a collection of property descriptors an instance of DataMember.
  /// </summary>
  public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
  {
   PropertyDescriptorCollection propertyDescriptors = base.GetProperties(attributes);
   List<ElementPropertyDescriptor> toRemove = new List<ElementPropertyDescriptor>();

   // Remove the properties that should not be shown when the class is not a DataMember
   DataMember source = this.ModelElement as DataMember;
   if ((source != null) && (!source.IsDataMember))
    foreach (ElementPropertyDescriptor propertyDescriptor in propertyDescriptors)
     if ((propertyDescriptor.DomainPropertyInfo.Id == DataMember.DataMemberNameDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == DataMember.EmitDefaultValueDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == DataMember.IsRequiredDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == DataMember.OrderDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == DataMember.VisibilityDomainPropertyId)
        )
      toRemove.Add(propertyDescriptor);

   foreach (PropertyDescriptor propertyDescriptor in toRemove)
    propertyDescriptors.Remove(propertyDescriptor);

   return propertyDescriptors;
  }
 }
 #endregion

 #region Type descriptor for MessageMember
 [TypeDescriptionProvider(typeof(MessageMemberDescriptionProvider))]
 partial class MessageMember
 {
 }

 /// <summary>
 /// Factory class for DataMemberTypeDescriptors.
 /// </summary>
 internal class MessageMemberDescriptionProvider : ElementTypeDescriptionProvider
 {
  /// <summary>
  /// Called by the System.ComponentModel framework when it requires a type descriptor instance.
  /// </summary>
  protected override ElementTypeDescriptor CreateTypeDescriptor(ICustomTypeDescriptor parent, ModelElement element)
  {
   return new MessageMemberTypeDescriptor(parent, element);
  }
 }

 /// <summary>
 /// Custom type descriptor class for MessageMember elements.
 /// </summary>
 public partial class MessageMemberTypeDescriptor : ElementTypeDescriptor
 {
  /// <summary>
  /// Creates a new DataMemberTypeDescriptor.
  /// </summary>
  public MessageMemberTypeDescriptor(ICustomTypeDescriptor parent, ModelElement selectedElement) : base(parent, selectedElement) { }

  /// <summary>
  /// Returns a collection of property descriptors an instance of DataMember.
  /// </summary>
  public override PropertyDescriptorCollection GetProperties(Attribute[] attributes)
  {
   PropertyDescriptorCollection propertyDescriptors = base.GetProperties(attributes);
   List<ElementPropertyDescriptor> toRemove = new List<ElementPropertyDescriptor>();

   // Remove the properties that should not be shown when the class is not a DataMember
   MessageMember source = this.ModelElement as MessageMember;
   if (source == null)
    return propertyDescriptors;

   switch (source.MessageMemberKind)
   {
    case MessageMemberKind.Normal:
     foreach (ElementPropertyDescriptor propertyDescriptor in propertyDescriptors)
      if ((propertyDescriptor.DomainPropertyInfo.Id == MessageMember.ActorDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.MustUnderstandDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.OrderDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.ProtectionLevelDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.RelayDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.WCFNameDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.WCFNamespaceDomainPropertyId)
         )
       toRemove.Add(propertyDescriptor);
     break;

    case MessageMemberKind.MessageBody:
     foreach (ElementPropertyDescriptor propertyDescriptor in propertyDescriptors)
      if (
            (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.ActorDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.MustUnderstandDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.OrderDomainPropertyId)
         || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.RelayDomainPropertyId)
        )
      toRemove.Add(propertyDescriptor);
     break;
    
    case MessageMemberKind.MessageHeader:
     break;
    
    case MessageMemberKind.MessageHeaderArray:
     // Unprocessed for the moment
     break;
    
    default:
     foreach (ElementPropertyDescriptor propertyDescriptor in propertyDescriptors)
      if ((propertyDescriptor.DomainPropertyInfo.Id == MessageMember.ActorDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.MustUnderstandDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.OrderDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.ProtectionLevelDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.RelayDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.WCFNameDomainPropertyId)
          || (propertyDescriptor.DomainPropertyInfo.Id == MessageMember.WCFNamespaceDomainPropertyId)
         )
       toRemove.Add(propertyDescriptor);
     break;
   }

   // Remove property descriptors
   foreach (PropertyDescriptor propertyDescriptor in toRemove)
    propertyDescriptors.Remove(propertyDescriptor);

   return propertyDescriptors;
  }
 }
 #endregion

}
